﻿@using Microsoft.AspNetCore.Components.Rendering
@using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure
@namespace Microsoft.FluentUI.AspNetCore.Components
@inherits FluentComponentBase
@typeparam TGridItem
<CascadingValue TValue="InternalGridContext<TGridItem>" IsFixed="true" Value="@_internalGridContext">
    @{
        StartCollectingColumns();
    }
    @if (!_manualGrid)
    {
        @ChildContent
    }
    <Defer>
        @{
            FinishCollectingColumns();
        }
        <ColumnsCollectedNotifier TGridItem="TGridItem" />

        <fluent-data-grid @ref=_gridReference
                          id="@Id"
                          no-tabbing=@NoTabbing
                          generate-header="none"
                          grid-template-columns=@_internalGridTemplateColumns
                          class="@GridClass()"
                          style="@Style"
                          aria-rowcount="@(_internalGridContext.TotalItemCount + 1)"
                          @onrowfocus=HandleOnRowFocusAsync
                          @onclosecolumnoptions="CloseColumnOptions"
                          @onclosecolumnresize="CloseColumnResize"
                          @attributes="AdditionalAttributes">
            @if (GenerateHeader != GenerateHeaderOption.None)
            {
                DataGridRowType headerType = DataGridRowType.Header;
                if (GenerateHeader == GenerateHeaderOption.Sticky)
                    headerType = DataGridRowType.StickyHeader;
                <FluentDataGridRow RowType=@headerType TGridItem=TGridItem>
                    @_renderColumnHeaders
                </FluentDataGridRow>
            }

            @if (Loading)
            {
                @_renderLoadingContent
            }
            else
            {
                @if (Virtualize)
                {
                    if (_internalGridContext.TotalItemCount == 0)
                    {
                        @_renderEmptyContent
                    }
                    else
                    {
                        <Virtualize @ref="@_virtualizeComponent"
                                    TItem="(int RowIndex, TGridItem Data)"
                                    ItemSize="@ItemSize"
                                    ItemsProvider="@ProvideVirtualizedItemsAsync"
                                    ItemContent="@(item => builder => RenderRow(builder, item.RowIndex, item.Data))"
                                    Placeholder="@(placeholderContext => builder => RenderPlaceholderRow(builder, placeholderContext))" />
                    }
                }
                else
                {
                    @_renderNonVirtualizedRows
                }
            }
            @if (_manualGrid)
            {
                @ChildContent
            }
        </fluent-data-grid>
    </Defer>
</CascadingValue>

@code {
    private void RenderNonVirtualizedRows(RenderTreeBuilder __builder)
    {
        var initialRowIndex = (GenerateHeader != GenerateHeaderOption.None) ? 2 : 1; // aria-rowindex is 1-based, plus 1 if there is a header
        var rowIndex = initialRowIndex;
        if (_internalGridContext.Items.Any())
        {
            foreach (var item in _internalGridContext.Items)
            {
                RenderRow(__builder, rowIndex++, item);
            }
        }
        else
        {
            RenderEmptyContent(__builder);
        }
    }

    private void RenderRow(RenderTreeBuilder __builder, int rowIndex, TGridItem item)
    {
        var rowClass = RowClass?.Invoke(item) ?? null;
        var rowStyle = RowStyle?.Invoke(item) ?? null;
        <FluentDataGridRow @key="@(ItemKey(item))" GridTemplateColumns=@_internalGridTemplateColumns aria-rowindex="@rowIndex" Class="@rowClass" Style="@rowStyle" TGridItem="TGridItem" Item="@item">
            @for (var colIndex = 0; colIndex < _columns.Count; colIndex++)
            {
                var col = _columns[colIndex];

                string? tooltip = col.Tooltip ? @col.RawCellContent(item) : null;

                <FluentDataGridCell GridColumn=@(colIndex+1) Class="@ColumnClass(col)" Style="@col.Style" @key="@col" TGridItem="TGridItem" Item="@item" title="@tooltip" aria-label="@tooltip">
                    @((RenderFragment)(__builder => col.CellContent(__builder, item)))
                </FluentDataGridCell>
            }
        </FluentDataGridRow>
    }

    private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext)
    {
        string? _rowsDataSize = $"height: {ItemSize}px";

        <FluentDataGridRow GridTemplateColumns=@GridTemplateColumns aria-rowindex="@(placeholderContext.Index + 1)" Style="@_rowsDataSize" TGridItem="TGridItem">
            @for (var colIndex = 0; colIndex < _columns.Count; colIndex++)
            {
                var col = _columns[colIndex];

                <FluentDataGridCell Class="@("grid-cell-placeholder " + @ColumnClass(col))" Style="@col.Style" @key="@col" GridColumn=@(colIndex+1) TGridItem="TGridItem">
                    @((RenderFragment)(__builder => col.RenderPlaceholderContent(__builder, placeholderContext)))
                </FluentDataGridCell>
            }
        </FluentDataGridRow>
    }

    private void RenderColumnHeaders(RenderTreeBuilder __builder)
    {
        @for (var colIndex = 0; colIndex < _columns.Count; colIndex++)
        {
            var col = _columns[colIndex];
            var oneBasedIndex = colIndex + 1;
            string CellId = Identifier.NewId();
            if (_sortByColumn == col)
                col.ShowSortIcon = true;
            else
                col.ShowSortIcon = false;

            <FluentDataGridCell GridColumn=@oneBasedIndex
                                CellType=DataGridCellType.ColumnHeader
                                Class="@("column-header " + @ColumnHeaderClass(col) + (ResizableColumns ? " resizable" : ""))"
                                Style="@col.Style" aria-sort="@AriaSortValue(col)"
                                @key="@col"
                                scope="col"
                                TGridItem="TGridItem">
                @col.HeaderContent

                @if (HeaderCellAsButtonWithMenu)
                {
                    @if (col == _displayOptionsForColumn)
                    {
                        <div class="col-options">
                            @col.ColumnOptions
                        </div>
                    }
                    @if (ResizableColumns && col == _displayResizeForColumn)
                    {
                        <div class="col-resize">

                            @if (ResizeType is not null)
                            {
                                <ColumnResizeOptions Column="@oneBasedIndex" ResizeType=@ResizeType TGridItem="TGridItem" />
                            }

                        </div>
                    }
                }
                else
                {
                    @if (col == _displayOptionsForColumn)
                    {
                        <div class="col-options">
                            <FluentStack Orientation="Orientation.Vertical">
                                @col.ColumnOptions
                                @if (ResizeType is not null)
                                {
                                    @if (@col.ColumnOptions is not null)
                                    {
                                        <FluentDivider Role="DividerRole.Separator" Style="width: 100%;" />
                                    }

                                    <ColumnResizeOptions Column="@oneBasedIndex" ResizeType=@ResizeType TGridItem="TGridItem" />
                                }

                            </FluentStack>
                        </div>
                    }
                }

                @if (ResizableColumns)
                {
                    <FluentDivider class="col-width-draghandle" Orientation="Orientation.Vertical" Role="DividerRole.Separator" />
                }
            </FluentDataGridCell>
        }
    }

    private void RenderEmptyContent(RenderTreeBuilder __builder)
    {
        @if (_manualGrid)
        {
            return;
        }
        // If we use the Blazor components here the renderer gets upset/lost, so we use the web components directly
        <fluent-data-grid-row class="empty-content-row" row-id="empty-row">
            <fluent-data-grid-cell class="empty-content-cell">
                @if (EmptyContent is null)
                {
                    @("No data to show!")
                }
                else
                {
                    @EmptyContent
                }
            </fluent-data-grid-cell>
        </fluent-data-grid-row>

    }

    private void RenderLoadingContent(RenderTreeBuilder __builder)
    {
        <FluentDataGridRow TGridItem="TGridItem" Class="loading-content-row">
            <FluentDataGridCell Class="loading-content-cell">
                @if (LoadingContent is null)
                {
                    <FluentStack HorizontalGap="3">
                        <FluentProgressRing Width="24px" /> <div>Loading...</div>
                    </FluentStack>
                }
                else
                {
                    @LoadingContent
                }
            </FluentDataGridCell>
        </FluentDataGridRow>
    }
}
